package com.example.demo.controller;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.example.demo.common.Constant;
import com.example.demo.model.entity.UserModel;
import com.example.demo.model.response.UserResponse;
import com.example.demo.service.impl.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.persistence.criteria.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;

@Controller
@RequestMapping(value = Constant.API_VERSION + "/user")
public class UserController {

    @Resource
    UserService userService;

    @Value("${level.common}")
    private String level;

    @RequestMapping(value = "/action/register", method = RequestMethod.POST)
    @ResponseBody
    public UserResponse register(@RequestHeader("Authorization") String token, @RequestBody UserModel userModel) throws Exception {
        if (StringUtils.isEmpty(userModel.getUserName())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "手机号码不能为空"));
        }
        if (StringUtils.isEmpty(userModel.getPassword())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "密码不能为空"));
        }
        UserModel exist = userService.getUserByUserName(userModel.getUserName(), userModel.getRole());
        if (exist != null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "该手机号码已注册"));
        }

        if (StringUtils.isEmpty(token)) {
            if (StringUtils.isEmpty(userModel.getCode())) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "验证码不能为空"));
            }

            if (Constant.messageMap.get(userModel.getUserName()) != null) {
                String code = Constant.messageMap.get(userModel.getUserName()).toString().split("_")[0];
                Long expire = Long.valueOf(Constant.messageMap.get(userModel.getUserName()).toString().split("_")[1]);
                if (expire < System.currentTimeMillis() || !code.equals(userModel.getCode())) {
                    throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "验证码错误"));
                }
                Constant.messageMap.remove(userModel.getUserName());
            } else {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "验证码错误"));
            }
        }

        if (StringUtils.isNotEmpty(userModel.getIdentityCard())) {
            String reg = "^\\d{15}$|^\\d{17}[0-9Xx]$";
            boolean idMatch = Pattern.matches(reg, userModel.getIdentityCard());
            if (!idMatch) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "身份证号码格式错误"));
            }
        }

        if (StringUtils.isNotEmpty(userModel.getEmail())) {
            String email = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
            boolean emailMatch = Pattern.matches(email, userModel.getEmail());
            if (!emailMatch) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "邮箱格式错误"));
            }
        }

        String pattern = "^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$";
        boolean isMatch = Pattern.matches(pattern, userModel.getUserName());
        if (!isMatch) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "手机号码格式错误"));
        }


        userModel.setPassword(DigestUtils.md5DigestAsHex((userModel.getPassword()).getBytes()));
        userModel.setUserId(UUID.randomUUID().toString());
        userModel.setCreateTime(System.currentTimeMillis());
        if (StringUtils.isEmpty(userModel.getLevelId())) { // TODO 设置普通会员
            userModel.setLevelId(level);
        }
        UserModel user = userService.save(userModel);
        UserResponse response = new UserResponse();
        org.springframework.beans.BeanUtils.copyProperties(user, response);
//        BeanUtils.copyProperties(response, user);
        return response;
    }


    @RequestMapping(value = "", method = RequestMethod.POST)
    @ResponseBody
    public void add(@RequestHeader("Authorization") String token, @RequestBody UserModel userModel) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        UserModel user = userService.getByUid(currentUid);
        if (user.getRole() == Constant.Role.USER.getRoleCode()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 403, "权限不足"));
        }
        UserModel exist = userService.getUserByUserName(userModel.getUserName(), userModel.getRole());
        if (exist != null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "该手机号码已注册"));
        }
        userModel.setNickName(userModel.getPhone());
        userModel.setPassword(DigestUtils.md5DigestAsHex((userModel.getPassword()).getBytes()));
        userModel.setUserId(UUID.randomUUID().toString());
        userModel.setCreateTime(System.currentTimeMillis());
        userService.save(userModel);
    }


    @RequestMapping(value = "/action/login", method = RequestMethod.POST)
    @ResponseBody
    public UserResponse login(@RequestBody final UserModel requestData) throws Exception {
        if (StringUtils.isEmpty(requestData.getUserName())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "手机号码不能为空"));
        }

        if (StringUtils.isNotEmpty(requestData.getCode())) {
            if (Constant.messageMap.get(requestData.getUserName()) != null) {
                String code = Constant.messageMap.get(requestData.getUserName()).toString().split("_")[0];
                Long expire = Long.valueOf(Constant.messageMap.get(requestData.getUserName()).toString().split("_")[1]);
                if (expire < System.currentTimeMillis() || !code.equals(requestData.getCode())) {
                    throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "验证码错误"));
                }
                Constant.messageMap.remove(requestData.getUserName());
            } else {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "验证码错误"));
            }
        } else {
            if (StringUtils.isEmpty(requestData.getPassword())) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "密码不能为空"));
            }
        }

        Page<UserModel> userPage = userService.findUserPage(new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<Predicate>();
                Path<String> namePath = root.get("userName");
                predicateList.add(criteriaBuilder.equal(namePath, requestData.getUserName()));
                Path<Integer> rolePath = root.get("role");
                if (requestData.getRole() == null) {
                    predicateList.add(criteriaBuilder.equal(rolePath, Constant.Role.USER.getRoleCode()));
                } else {
                    predicateList.add(criteriaBuilder.lt(rolePath, Constant.Role.USER.getRoleCode()));
                }
                criteriaQuery.where(predicateList.toArray(new Predicate[predicateList.size()]));
                return null;
            }
        }, new PageRequest(0, 10));

        List<UserModel> userList = userPage.getContent();
        UserModel user = null;
        if (userList.size() > 0) {
            user = userList.get(0);
        }

        if (user != null && StringUtils.isNotEmpty(requestData.getShopId()) && (!user.getShopId().equals(requestData.getShopId())
                && user.getRole() != Constant.Role.ADMIN.getRoleCode())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "权限不足"));
        }
        if (user != null && StringUtils.isNotEmpty(requestData.getCode())) {
            if (Constant.loginMap.containsKey(user.getUserId()) && user.getRole() == Constant.Role.USER.getRoleCode()) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "该账号已在其他设备登录"));
            }
            Constant.loginMap.put(user.getUserId(), System.currentTimeMillis());
            BASE64Encoder encoder = new BASE64Encoder();
            user.setToken(encoder.encode(user.getUserId().getBytes()));
            UserResponse response = new UserResponse();
            org.springframework.beans.BeanUtils.copyProperties(user, response);
            return response;
        }

        if (user != null && DigestUtils.md5DigestAsHex(requestData.getPassword().getBytes()).equals(user.getPassword())) {
            if (Constant.loginMap.containsKey(user.getUserId()) && user.getRole() == Constant.Role.USER.getRoleCode()) {
                throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "该账号已在其他设备登录"));
            }
            Constant.loginMap.put(user.getUserId(), System.currentTimeMillis());
            BASE64Encoder encoder = new BASE64Encoder();
            user.setToken(encoder.encode(user.getUserId().getBytes()));
            UserResponse response = new UserResponse();
            org.springframework.beans.BeanUtils.copyProperties(user, response);
            return response;
        } else {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "账号或密码错误"));
        }

    }


    @RequestMapping(value = "/action/check", method = RequestMethod.POST)
    @ResponseBody
    public void check(@RequestBody UserModel userModel) throws Exception {
        if (StringUtils.isEmpty(userModel.getUserName())) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "手机号码不能为空"));
        }
        String pattern = "^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$";
        boolean isMatch = Pattern.matches(pattern, userModel.getUserName());
        if (!isMatch) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "手机号码格式错误"));
        }

        int code = (int) (Math.random() * 8999) + 1000;
        final String product = "Dysmsapi";//短信API产品名称（短信产品名固定，无需修改）
        final String domain = "dysmsapi.aliyuncs.com";//短信API产品域名（接口地址固定，无需修改）
        //替换成你的AK
        final String accessKeyId = "LTAI0PMpgo4ZquQk";//你的accessKeyId,参考本文档步骤2
        final String accessKeySecret = "9FTDw3C29tmAHpEBIPyrvSEpHPXgND";//你的accessKeySecret，参考本文档步骤2
        //初始化ascClient,暂时不支持多region（请勿修改）
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,
                accessKeySecret);
        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        IAcsClient acsClient = new DefaultAcsClient(profile);
        //组装请求对象
        SendSmsRequest request = new SendSmsRequest();
        //使用post提交
        request.setMethod(MethodType.POST);
        request.setSignName("厦门Hyone");
        request.setTemplateCode("SMS_136820069");
        request.setPhoneNumbers(userModel.getUserName());
        request.setTemplateParam("{\"code\":\"" + code + "\"}");
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
        if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {

        } else {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "发送失败"));
        }
        Constant.messageMap.put(userModel.getUserName(), "" + code + "_" + System.currentTimeMillis() + 5 * 1000 * 60);

    }


    @RequestMapping(value = "/action/logout", method = RequestMethod.POST)
    @ResponseBody
    public void logout(@RequestHeader("Authorization") String token) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        if (Constant.loginMap.get(currentUid) != null) {
            Constant.loginMap.remove(currentUid);
        }
    }

    @RequestMapping(value = "/{user_id}", method = RequestMethod.PUT)
    @ResponseBody
    public UserResponse updateUser(@RequestHeader("Authorization") String token, @PathVariable(value = "user_id") String userId, @RequestBody UserModel model) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        UserModel current = userService.getByUid(currentUid);
        if (!userId.equals(currentUid) && current.getRole() == Constant.Role.USER.getRoleCode()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 403, "权限不足"));
        }
        UserModel user = null;
        if (userId.equals(currentUid)) {
            user = userService.getByUid(currentUid);
        } else {
            user = userService.getByUid(userId);
        }

        UserResponse response = new UserResponse();
        if (user != null) {
//            if (StringUtils.isNotEmpty(model.getUserName())) {
//                user.setUserName(model.getUserName());
//            }
            if (StringUtils.isNotEmpty(model.getShopId())) {
                user.setShopId(model.getShopId());
            }
            if (StringUtils.isNotEmpty(model.getLevelId())) {
                user.setLevelId(model.getLevelId());
            }
            if (StringUtils.isNotEmpty(model.getPassword())) {
                user.setPassword(DigestUtils.md5DigestAsHex(model.getPassword().getBytes()));
            }
            if (StringUtils.isNotEmpty(model.getPhone())) {
                user.setPhone(model.getPhone());
            }
            if (StringUtils.isNotEmpty(model.getEmail())) {
                user.setEmail(model.getEmail());
            }
            if (StringUtils.isNotEmpty(model.getIdentityCard())) {
                String reg = "^\\d{15}$|^\\d{17}[0-9Xx]$";
                boolean idMatch = Pattern.matches(reg, model.getIdentityCard());
                if (!idMatch) {
                    throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "身份证号码格式错误"));
                }
                user.setIdentityCard(model.getIdentityCard());
            }
            if (StringUtils.isNotEmpty(model.getRealName())) {
                user.setRealName(model.getRealName());
            }
            if (StringUtils.isNotEmpty(model.getNickName())) {
                user.setNickName(model.getNickName());
            }
            if (StringUtils.isNotEmpty(model.getUserPhoto())) {
                user.setUserPhoto(model.getUserPhoto());
            }
            userService.save(user);
            org.springframework.beans.BeanUtils.copyProperties(user, response);
        } else {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "用户不存在"));
        }
        return response;
    }

    @RequestMapping(value = "/{user_id}", method = RequestMethod.GET)
    @ResponseBody
    public UserResponse getUser(@RequestHeader("Authorization") String token, @PathVariable(value = "user_id") String userId) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        UserModel user = userService.getByUid(currentUid);
        if (!userId.equals(currentUid) && user.getRole() == Constant.Role.USER.getRoleCode()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 403, "权限不足"));
        }
        UserModel targetUser = userService.getByUid(userId);

        UserResponse response = new UserResponse();
        if (user == null) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 400, "用户不存在"));
        }
        org.springframework.beans.BeanUtils.copyProperties(targetUser, response);
        return response;
    }


    @RequestMapping(value = "/{user_id}", method = RequestMethod.DELETE)
    @ResponseBody
    public void deleteUser(@RequestHeader("Authorization") String token, @PathVariable(value = "user_id") String userId) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String currentUid = new String(decoder.decodeBuffer(token), "UTF-8");
        UserModel user = userService.getByUid(currentUid);
        if (user.getRole() == Constant.Role.USER.getRoleCode()) {
            throw new RuntimeException(MessageFormat.format(Constant.ERROR_FORMAT, 403, "权限不足"));
        }
        userService.deleteUser(userId);
    }


    @RequestMapping(value = "", method = RequestMethod.GET)
    @ResponseBody
    public JSONObject getUserList(@RequestParam(value = "page_size", defaultValue = "10") String pageSize, @RequestParam(value = "page_number", defaultValue = "1") String pageNumber,
                                  @RequestParam(value = "role", defaultValue = "") final String role, @RequestParam(value = "shop_id", defaultValue = "") final String shopId,
                                  @RequestParam(value = "keyword", defaultValue = "") final String keyword) throws Exception {
        Page<UserModel> page = userService.findUserPage(new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicateList = new ArrayList<Predicate>();
                if (StringUtils.isNotEmpty(shopId)) {
                    Path<String> shopIdPath = root.get("shopId");
                    predicateList.add(criteriaBuilder.equal(shopIdPath, shopId));
                }
                if (StringUtils.isNotEmpty(role)) {
                    Path<Integer> rolePath = root.get("role");
                    predicateList.add(criteriaBuilder.equal(rolePath, role));
                }
                if (StringUtils.isNotEmpty(keyword)) {
                    Path<String> namePath = root.get("userName");
                    Path<String> phonePath = root.get("phone");
                    predicateList.add(criteriaBuilder.or(criteriaBuilder.like(namePath, "%" + keyword + "%"), criteriaBuilder.like(phonePath, "%" + keyword + "%")));
                }

                criteriaQuery.where(predicateList.toArray(new Predicate[predicateList.size()]));
                return null;
            }
        }, new PageRequest(Integer.valueOf(pageNumber) - 1, Integer.valueOf(pageSize)));

        List<UserResponse> responseList = new ArrayList<UserResponse>();
        for (UserModel u : page.getContent()) {
            UserResponse response = new UserResponse();
            org.springframework.beans.BeanUtils.copyProperties(u, response);
            responseList.add(response);
        }
        JSONObject result = new JSONObject();
        result.put("total", page.getTotalElements());
        result.put("items", responseList);
        return result;
    }


}
